
import { _decorator, Component, Node, random, Vec2 } from 'cc';
import { DamageStruct, FightControl, GameModel } from '../fight/FightControl';
import { DataHelper } from '../system/DataHelper';
import { SecondaryGunStruct, GameData } from '../system/GameData';
import { secondGun_specialSkill_config } from '../manager/AppControll';
import { Move } from '../fight/component/Move';
import { LevelMonsterManager } from '../fight/levelModel/LevelMonsterManager';
import { MonsterManager } from '../fight/monster/MonsterManager';
import { randomGunWeight } from '../pop/SecondGunRandom';
const { ccclass, property } = _decorator;


@ccclass('Tools')
export class Tools {
    static RemoveElementByVaule(arr: any[], target: any) {
        let index = arr.indexOf(target);
        if (index !== -1) {
            arr.splice(index, 1);
        }
    }

    static CalculateDamage(atk, CHitRate, CHitDamage, DamageBoost = 0, time: number = 0, n: number = 0): DamageStruct {
        n = GameData.giftDmg;
        let randomNum = Math.random();
        let isCHit = false;
        let damage = 0;
        let revision = 0.8 + Math.random() * 0.2;
        if (CHitRate / 100 > randomNum) {
            isCHit = true;
        } else {
            isCHit = false;
            CHitDamage = 100;
        }
        damage = atk * CHitDamage / 100 * (1 + DamageBoost / 100) * (1 + n) * revision
        let dmg: DamageStruct = {
            isCriticalHit: isCHit,
            damage: damage,
            time: time
        }
        return dmg;
    }

    //一元二次方程求解
    static SolveQuadraticEquation(a: number, b: number, c: number): number {
        const discriminant = b * b - 4 * a * c;
        if (discriminant < 0) {
            return null; // no real roots
        } else if (discriminant === 0) {
            return -b / (2 * a) // one real root
        } else {
            const root1 = (-b + Math.sqrt(discriminant)) / (2 * a);
            const root2 = (-b - Math.sqrt(discriminant)) / (2 * a);
            let res = root1 >= 0 ? root1 : root2;
            return res; // two real roots
        }
    }

    static GetResultByWeightLt(pool: number[][]) {
        let totalWeight = 0;
        let weightSum = 0;
        pool.forEach((element) => {
            totalWeight += element[1];
        })
        let randomNumber = Math.random();
        for (let i = 0; i < pool.length; i++) {
            weightSum += pool[i][1];
            if (weightSum >= randomNumber * totalWeight) {
                return pool[i][0];
            }
        }
    }

    static GetNewSecondaryGun(): SecondaryGunStruct {
        let secondGunConfig: secondGun_specialSkill_config = DataHelper.GetRandomGun();
        let lv: number = DataHelper.GetSecondLv();
        let sct: SecondaryGunStruct = {
            level: lv,
            configId: secondGunConfig.skill
        }
        return sct;
    }

    static GetHitTime(sp0: number, target: Node, starPoint, barrelLength): number {
        let sp1 = target.getComponent(Move).Speed;
        let temp = target.position.clone().subtract(starPoint);
        let N = temp.length();
        let a = new Vec2(temp.x, temp.y);
        let b = target.getComponent(Move).GetDirection();
        let cosθ = a.clone().dot(b.clone().multiplyScalar(-1)) / (a.length() * b.length());
        let ta = sp1 * sp1 - sp0 * sp0;
        let tb = cosθ * 2 * sp1 * N * -1;
        let tc = N * N;
        let t = Tools.SolveQuadraticEquation(ta, tb, tc) - barrelLength / sp0;
        return t;
    }

    static GetHitPositinByTime(t: number, target) {
        if (t) {
            let point = target.getComponent(Move).GetPointByTime(t);
            return point;
        } else {
            return null;
        }
    }

    static FormatNumber(value: number): string {
        const suffixes = ["", "k", "m", "b", "t"];
        const suffixIndex = Math.floor(Math.log10(value) / 3);
        const shortValue = value / Math.pow(1000, suffixIndex);
        const roundedValue = Math.round(shortValue * 10) / 10;
        if (value < 1000) {
            return Math.round(value) + "";
        } else {
            return roundedValue.toFixed(2) + suffixes[suffixIndex];
        }

    }

    static GetLtMonster(): Node[] {
        let lt = [];
        if (FightControl.gamemodel == GameModel.normal) {
            lt = MonsterManager.ltMonster;
        } else if (FightControl.gamemodel == GameModel.levelModel) {
            lt = LevelMonsterManager.ltMonster;
        }
        return lt
    }

    static formatCountdown(seconds: number): string {
        const hours = Math.floor(seconds / 3600);
        const minutes = Math.floor((seconds % 3600) / 60);
        const remainingSeconds = seconds % 60;

        const formattedHours = hours.toString().padStart(2, '0');
        const formattedMinutes = minutes.toString().padStart(2, '0');
        const formattedSeconds = remainingSeconds.toFixed(0).toString().padStart(2, '0');

        return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
    }
}

/**
 * [1] Class member could be defined like this.
 * [2] Use `property` decorator if your want the member to be serializable.
 * [3] Your initialization goes here.
 * [4] Your update function goes here.
 *
 * Learn more about scripting: https://docs.cocos.com/creator/3.4/manual/zh/scripting/
 * Learn more about CCClass: https://docs.cocos.com/creator/3.4/manual/zh/scripting/decorator.html
 * Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.4/manual/zh/scripting/life-cycle-callbacks.html
 */
